package perfume

import (
	"context"
	"strconv"
	"strings"

	"mall/common/ctxdatax"
	"mall/common/globalkey"
	"mall/common/moneyx"
	"mall/common/resultx"
	"mall/service/backend/common/utils/pointy"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/api/internal/logic/util"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/forum/api/internal/utils/parse"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetSearchLogListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetSearchLogListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSearchLogListLogic {
	return &GetSearchLogListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetSearchLogListLogic) GetSearchLogList(req *types.SearchLogListReq) (*types.SearchLogListInfo, error) {
	userId := ctxdatax.GetUserId(l.ctx)
	if userId == 0 {
		return nil, resultx.NewErrCode(resultx.TOKEN_EXPIRE_ERROR)
	}

	page, pageSize := parse.ParsePageInfo(
		req.Current,
		req.PageSize,
		l.svcCtx.Config.Query.DefaultAmount,
		l.svcCtx.Config.Query.MaxAmount,
	)

	var preload string = "blogBook:Id,Title,Slug;blogMedia:Id,Uid,Url,Thumbnail;blogBookMeta:year,reviewCount,averageRating"
	var eagerLoad string = "blogBook:blogMedia,blogBookMeta"
	var with string
	if req.With != nil {
		with = strings.TrimSpace(*req.With)
	}
	if len(with) > 0 {
		preload += ";blogBookRelation:" + with
		eagerLoad += ",blogBookRelation"
	}
	var logTypeKnowledgeBase string = strconv.FormatInt(int64(globalkey.PostTypeKnowledgeBase), 10)
	var filter string = "logSlug,equalTo:perfumes;logType,equalTo:" + logTypeKnowledgeBase
	if req.Filter != nil && len(strings.TrimSpace(*req.Filter)) > 0 {
		filterMap := util.GetFilterMap(strings.TrimSpace(*req.Filter))
		for key, _ := range filterMap {
			switch key {
			case "brand":
				filter = "logSlug,equalTo:brands;logType,equalTo:" + logTypeKnowledgeBase
			case "perfume":
				filter = "logSlug,equalTo:perfumes;logType,equalTo:" + logTypeKnowledgeBase
			case "nose":
				filter = "logSlug,equalTo:perfumers;logType,equalTo:" + logTypeKnowledgeBase
			case "group":
				filter = "logSlug,equalTo:fragrance families;logType,equalTo:" + logTypeKnowledgeBase
			case "note":
				filter = "logSlug,equalTo:notes;logType,equalTo:" + logTypeKnowledgeBase
			}
		}
	}
	var sorter string
	if req.Sorter != nil {
		sorter = strings.TrimSpace(*req.Sorter)
	}
	var platformId uint32 = globalkey.ThirdPartyPlatformWechatMini

	res, err := l.svcCtx.BlogRpc.SearchLogList(l.ctx, &blogclient.SearchLogListReq{
		Offset:     int32((page - 1) * pageSize),
		Limit:      int32(pageSize),
		Preload:    preload,
		EagerLoad:  eagerLoad,
		Filter:     filter,
		Sorter:     sorter,
		VisitorId:  int64(userId),
		PlatformId: int32(platformId),
	})
	if err != nil {
		return nil, err
	}

	var hasNextPage bool
	var hasPreviousPage bool
	if res.HasNextPage > 0 {
		hasNextPage = true
	}
	if res.HasPreviousPage > 0 {
		hasPreviousPage = true
	}

	resp := &types.SearchLogListInfo{
		BaseListInfo: types.BaseListInfo{
			Current:         page,
			PageSize:        pageSize,
			HasNextPage:     hasNextPage,
			HasPreviousPage: hasPreviousPage,
		},
	}

	if len(res.Data) > 0 {
		for _, item := range res.Data {
			var sections []*types.TermInfo
			if len(item.Sections) > 0 {
				for _, v := range item.Sections {
					sections = append(sections, &types.TermInfo{
						Id:   pointy.GetPointer(uint64(v.Id)),
						Name: pointy.GetPointer(v.Name),
						Slug: pointy.GetPointer(v.Slug),
					})
				}
			}
			var media []*types.TmpMediaInfo
			if len(item.Media) > 0 {
				for _, v := range item.Media {
					media = append(media, &types.TmpMediaInfo{
						Uid:       pointy.GetPointer(uint64(v.Uid)),
						Id:        pointy.GetPointer(strconv.FormatInt(int64(v.Id), 10)),
						Url:       pointy.GetPointer(v.Url),
						Thumbnail: pointy.GetPointer(uint32(v.Thumbnail)),
					})
				}
			}
			var brand []*types.KbEntryInfo
			var perfume []*types.KbEntryInfo
			var nose []*types.KbEntryInfo
			var group []*types.KbEntryInfo
			var topNote []*types.KbEntryInfo
			var heartNote []*types.KbEntryInfo
			var baseNote []*types.KbEntryInfo
			if len(item.Relations) > 0 {
				for _, v := range item.Relations {
					switch v.Section {
					case "brand":
						brand = append(brand, &types.KbEntryInfo{
							Id:    pointy.GetPointer(uint64(v.Id)),
							Title: pointy.GetPointer(v.Title),
							Slug:  pointy.GetPointer(v.Slug),
						})
					case "perfume":
						perfume = append(perfume, &types.KbEntryInfo{
							Id:    pointy.GetPointer(uint64(v.Id)),
							Title: pointy.GetPointer(v.Title),
							Slug:  pointy.GetPointer(v.Slug),
						})
					case "nose":
						nose = append(nose, &types.KbEntryInfo{
							Id:    pointy.GetPointer(uint64(v.Id)),
							Title: pointy.GetPointer(v.Title),
							Slug:  pointy.GetPointer(v.Slug),
						})
					case "group":
						group = append(group, &types.KbEntryInfo{
							Id:    pointy.GetPointer(uint64(v.Id)),
							Title: pointy.GetPointer(v.Title),
							Slug:  pointy.GetPointer(v.Slug),
						})
					case "note":
						switch int32(v.GroupId) {
						case globalkey.KBEntryTopNote:
							topNote = append(topNote, &types.KbEntryInfo{
								Id:    pointy.GetPointer(uint64(v.Id)),
								Title: pointy.GetPointer(v.Title),
								Slug:  pointy.GetPointer(v.Slug),
							})
						case globalkey.KBEntryHeartNote:
							heartNote = append(heartNote, &types.KbEntryInfo{
								Id:    pointy.GetPointer(uint64(v.Id)),
								Title: pointy.GetPointer(v.Title),
								Slug:  pointy.GetPointer(v.Slug),
							})
						case globalkey.KBEntryBaseNote:
							baseNote = append(baseNote, &types.KbEntryInfo{
								Id:    pointy.GetPointer(uint64(v.Id)),
								Title: pointy.GetPointer(v.Title),
								Slug:  pointy.GetPointer(v.Slug),
							})
						}
					}
				}
			}
			var year *string
			var reviewCount *uint32
			var averageRating *string
			var recommended *bool
			if len(item.Meta) > 0 {
				for _, v := range item.Meta {
					switch v.Key {
					case "year":
						year = pointy.GetPointer(v.Value)
					case "reviewCount":
						if i, err := strconv.ParseInt(v.Value, 10, 32); err == nil {
							reviewCount = pointy.GetPointer(uint32(i))
						}
					case "averageRating":
						if f, err := strconv.ParseFloat(v.Value, 64); err == nil {
							averageRating = pointy.GetPointer(moneyx.FormatStar(f, 1))
						}
					case "recommended":
						recommended = pointy.GetPointer(true)
					}
				}
			}

			resp.List = append(resp.List, &types.KbEntryInfo{
				Id:            pointy.GetPointer(uint64(item.Id)),
				Title:         pointy.GetPointer(item.Title),
				Slug:          pointy.GetPointer(item.Slug),
				CommentStatus: pointy.GetPointer(uint32(item.CommentStatus)),
				CreatedAt:     pointy.GetPointer(item.Date),
				UpdatedAt:     pointy.GetPointer(item.Modified),
				Sections:      sections,
				Media:         media,
				Brands:        brand,
				Perfumes:      perfume,
				Noses:         nose,
				Groups:        group,
				TopNotes:      topNote,
				HeartNotes:    heartNote,
				BaseNotes:     baseNote,
				Year:          year,
				AverageRating: averageRating,
				ReviewCount:   reviewCount,
				Recommended:   recommended,
			})
		}
	}

	return resp, nil
}
